#include "Bat.h"
#include "DestroyGameObjectMessage.h"
#include "Game.h"
#include "AnimationSystem.h"
#include "GameplayState.h"
#include "Player.h"
#include "TileSystem.h"
#include "../SGD Wrappers/SGD_AudioManager.h"

Bat::Bat()
{
	useGravity = false;
	patrolDirectionRight = rand() % 2 ? true : false;

	SetCurrAnimation("bat_flying");
	AnimationSystem::GetInstance()->StartPlaying(animInfo);
	AnimationSystem::GetInstance()->StartLooping(animInfo);
}

void Bat::Update(float elapsedTime)
{
	Enemy::Update(elapsedTime);
	if (!updating) return;
}

/*virtual*/ void Bat::MoveLeft(float speed)
{
	m_vtVelocity = { 0.0f, 0.0f };
	Enemy::MoveLeft(speed);
}

/*virtual*/ void Bat::MoveRight(float speed)
{
	m_vtVelocity = { 0.0f, 0.0f };
	Enemy::MoveRight(speed);
}

/*virtual*/ void Bat::EnterPatrol()
{
	if (state == State::PATROL) return;
	StartAnimation("bat_flying");
	Enemy::EnterPatrol();

	int range = (int)m_ptPosition.y - 400;
	if (range == 0) range++;
	goUp = float(rand() % range + 200);
}

/*virtual*/ void Bat::EnterCloseIn()
{
	if (state == State::ATTACK) return;
	StartAnimation("bat_swooping");
	Enemy::EnterAttack();
}

/*virtual*/ bool Bat::DoAttack()
{
	float leniancy = 0.13f;
	if (state == State::ATTACK) leniancy = 0.3f;

	SGD::Point playerPos = GameplayState::GetInstance()->GetPlayer()->GetPosition();

	float angleToPlayer = (playerPos - m_ptPosition).ComputeNormalized().ComputeAngle({ 0, 1 });

	if (patrolDirectionRight && playerPos.x > m_ptPosition.x && abs(angleToPlayer - SGD::PI / 4) < leniancy)
		return true;
	else if (!patrolDirectionRight && playerPos.x < m_ptPosition.x && abs(angleToPlayer - SGD::PI / 4) < leniancy)
		return true;

	return false;
}

/*virtual*/ void Bat::Attack()
{
	GameplayState *gameplay = GameplayState::GetInstance();
	SGD::Point playerPos = gameplay->GetPlayer()->GetPosition();
	playerPos.y -= 20.0f;

	if ((playerPos - m_ptPosition).ComputeLength() < 15.0f)
	{
		EnterPatrol();
	}

	//Get bat to head towards player
	SGD::Vector toPlayer = playerPos - m_ptPosition;
	toPlayer.Normalize();
	toPlayer *= 300;
	m_vtVelocity = toPlayer;
}

void Bat::SetOwner(Vampire *set)
{
	owner = set;
}

/*virtual*/ void Bat::Patrol()
{
	GameplayState *gameplay = GameplayState::GetInstance();
	TileSystem *TS = TileSystem::GetInstance();

	bool rightWall = TS->CheckCollison(gameplay->GetMapIndex(), { GetRect().right + 70, GetPosition().y });
	bool leftWall = TS->CheckCollison(gameplay->GetMapIndex(), { GetRect().left - 70, GetPosition().y });
	bool ceiling = TS->CheckCollison(gameplay->GetMapIndex(), { GetPosition().x, GetRect().top - 50 });
	bool floor = TS->CheckCollison(gameplay->GetMapIndex(), { GetPosition().x, GetRect().bottom + 50 });

	if (owner)
	{
		SGD::Point playerPos = gameplay->GetPlayer()->GetPosition();
		if (abs(m_ptPosition.x - playerPos.x) > 250.0f)
		{
			if (m_ptPosition.x < playerPos.x) patrolDirectionRight = true;
			else patrolDirectionRight = false;
		}
	}

	if (patrolDirectionRight)
	{
		if (rightWall)
			patrolDirectionRight = false;
		else MoveRight();
	}
	else
	{
		if (leftWall || m_ptPosition.x < 50.0f)
			patrolDirectionRight = true;
		else MoveLeft();
	}

	//go towards target height
	if (m_ptPosition.y < goUp && !floor)
	{
		m_vtVelocity.y = 50;
	}
	else if (!ceiling)
	{
		m_vtVelocity.y = -50;
	}
}

void Bat::HandleCollision(GameObject* pOther)
{
	if (pOther->GetType() == MovingObject::OBJ_BULLET)
	{
		// call MovingObjects HandleCollision
		MovingObject::HandleCollision(pOther);
		// play hit sfx
		SGD::AudioManager::GetInstance()->PlayAudio(damageAudio);
	}
	if (pOther->GetType() == MovingObject::OBJ_PLAYER)
	{
		// create rect for pastPosition
		if (animInfo.GetCurrAnimation() != "" && AnimationSystem::GetInstance()->Contains(animInfo.GetCurrAnimation()))
		{
			//shortcuts
			SGD::Rectangle colRect = pastCollisionRect;

			//Return the current collision rectangle
			pastRect = { SGD::Point(pastPosition.x - pastAnchorPoint.x + colRect.left, pastPosition.y - pastAnchorPoint.y + colRect.top),
				SGD::Size(colRect.ComputeWidth(), colRect.ComputeHeight()) };
		}

		// create rect for pOther->Location
		SGD::Rectangle otherRect;
		if (animInfo.GetCurrAnimation() != "" && AnimationSystem::GetInstance()->Contains(animInfo.GetCurrAnimation()))
		{
			//shortcuts
			Frame currFrame = AnimationSystem::GetInstance()->GetLoaded()[animInfo.GetCurrAnimation()].GetFrames()[animInfo.GetCurrFrame()];
			SGD::Rectangle colRect = currFrame.GetCollisionRect();
			SGD::Point pt = currFrame.GetAnchorPoint();

			//Return the current collision rectangle
			otherRect = { SGD::Point(pOther->GetPosition().x - pt.x + colRect.left, pOther->GetPosition().y - pt.y + colRect.top),
				SGD::Size(colRect.ComputeWidth(), colRect.ComputeHeight()) };
		}


		if (GameplayState::GetInstance()->CheckCharacterCollision(pastRect, GetRect(), otherRect))
		{
			Player* player = dynamic_cast<Player*>(pOther);
			if (player)
			{
				if (GameplayState::GetInstance()->top || GameplayState::GetInstance()->bottom)
					m_iHealth -= player->GetDamage();
			}
		}
	}

	if (m_iHealth <= 0 && owner)
	{
		owner->BatDead(m_ptPosition);
	}

}
